// Thud - a dynamic object-oriented language
// Copyright (C) 2009,2010 David H. Hovemeyer <david.hovemeyer@gmail.com>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

/*
 * Constant.h
 *
 *  Created on: Dec 1, 2009
 *      Author: dhovemey
 */

#ifndef CONSTANT_H_
#define CONSTANT_H_

#include <cstdint>
#include <string>
#include "vm/IPersistent.h"
#include "vm/ConstantType.h"
class ConstantPool;
class IConstantVisitor;

/**
 * A constant value or class reference in the ConstantPool for a Class.
 */
class Constant : public IPersistent {
private:
	ConstantType m_type;

	Constant(const Constant &);
	Constant& operator=(const Constant &);

public:
	/**
	 * Constructor.
	 * @param type the ConstantType of the constant
	 */
	Constant(ConstantType type);

	/** Destructor. */
	virtual ~Constant();

	/** Get the ConstantType of this constant. */
	ConstantType getType() const { return m_type; }

	/** Get the tag byte used to identify the constant in the serialized representation of the ConstantPool. */
	virtual uint8_t getTagByte() const = 0;

	/**
	 * Return the value of the constant as a string.
	 *
	 * @param cp the ConstantPool containing this Constant
	 */
	virtual std::wstring asString(ConstantPool *cp) const = 0;

	/**
	 * Accept given constant visitor.
	 *
	 * @param visitor a constant visitor
	 */
	virtual void accept(IConstantVisitor *visitor) = 0;

	/**
	 * Determine if this Constant compares as less than
	 * another Constant.
	 * May only be used to compare constants of the same type!
	 *
	 * @param other another Constant
	 * @return true if this constant is less than other, false otherwise
	 */
	virtual bool compare(const Constant *other) const = 0;

	/**
	 * Write a Constant to given DataOutputStream.
	 * @param out the DataOutputStream to write to
	 * @param c   the Constant that should be written
	 */
	static void writeConstant(DataOutputStream *out, const Constant *c);

	/**
	 * Read a Constant from given DataInputStream.
	 *
	 * @param in the DataInputStream to read from
	 * @return the Constant that was read
	 */
	static Constant* readConstant(DataInputStream *in);

	/**
	 * Compare two constants to determine if the left one is less than the right one.
	 * Defines a total order for all constants.
	 *
	 * @param left the left Constant
	 * @param right the right Constant
	 * @return true if left Constant is less than right, false otherwise
	 */
	static bool lessThan(const Constant *left, const Constant *right);
};

#endif /* CONSTANT_H_ */
